package cn.org.donald.framework.service.impl;

import cn.org.donald.framework.service.SysMenuService;
import cn.org.donald.framework.service.SysRoleMenuService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.org.donald.framework.pojo.dto.PageDto;
import cn.org.donald.framework.pojo.vo.MenuTreeVo;
import cn.org.donald.framework.util.ListUtil;
import cn.org.donald.mapper.MenuMapper;
import cn.org.donald.pojo.entity.system.Menu;
import cn.org.donald.pojo.entity.system.RoleMenu;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Donald
 * @since 2020-11-09
 */
@Service(interfaceClass = SysMenuService.class, version = "1.0.0",group = "donald")
public class SysMenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements SysMenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public List<MenuTreeVo> findTree(PageDto<Menu> pageDto) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>(pageDto.getQuery());
        List<Menu> menuList = menuMapper.selectList(queryWrapper);
        if (ListUtil.isEmptyOrHasClassFieldAllEmpty(menuList)){
            return new ArrayList<>();
        }
        return sortAndGetParent(menuList);
    }

    /**
     * 根据roleId获取集合
     * @param ids
     * @return
     */
    @Override
    public List<MenuTreeVo> findTreeByRoleIds(Long... ids) {
        List<Long> idList = new ArrayList<>(Arrays.asList(ids));

        QueryWrapper<RoleMenu> roleMenuQueryWrapper = new QueryWrapper<>();
        roleMenuQueryWrapper.in("role_id", idList);
        List<RoleMenu> roleMenuList = sysRoleMenuService.list(roleMenuQueryWrapper);
        if (ListUtil.isEmptyOrHasClassFieldAllEmpty(roleMenuList)){
            return new ArrayList<>();
        }
        List<Long> longs = new ArrayList<>();
        roleMenuList.forEach(roleMenu -> longs.add(roleMenu.getMenuId()));
        List<Menu> menuList = menuMapper.selectBatchIds(longs);
        if (ListUtil.isEmptyOrHasClassFieldAllEmpty(menuList)){
            return new ArrayList<>();
        }
        return sortAndGetParent(menuList);
    }

    @Override
    public List<MenuTreeVo> findTreeByNotRoleId(Long id) {
        QueryWrapper<RoleMenu> roleMenuQueryWrapper = new QueryWrapper<>();
        roleMenuQueryWrapper.eq("role_id",id);
        List<RoleMenu> roleMenus = sysRoleMenuService.list(roleMenuQueryWrapper);
        List<Long> longs = new ArrayList<>();
        roleMenus.forEach(roleMenu -> longs.add(roleMenu.getMenuId()));

        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.notIn("id",longs);
        List<Menu> menuList = menuMapper.selectList(queryWrapper);
        return sortAndGetParent(menuList);
    }

    @Override
    public List<Menu> findByParentId(Long id) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",id);
        return menuMapper.selectList(queryWrapper);
    }

    @Override
    public List<Menu> getParentList() {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", 0);
        queryWrapper.or();
        queryWrapper.isNull("parent_id");
        return super.list(queryWrapper);
    }

    /**
     * 递归树
     * @param menuVoParent
     * @param menuVos
     * @return
     */
    private List<MenuTreeVo> getChildren(MenuTreeVo menuVoParent, List<MenuTreeVo> menuVos){
        return menuVos.stream().filter(menuVo -> menuVo.getParentId() !=null && menuVo.getParentId().equals(menuVoParent.getId()))
                .peek(menuVo -> menuVo.setChildren(getChildren(menuVo,menuVos)))
                .collect(Collectors.toList());
    }


    /**
     * 排序并获得最顶级过滤最顶级菜单
     * @param menuList
     * @return
     */
    private List<MenuTreeVo> sortAndGetParent(List<Menu> menuList){
        List<MenuTreeVo> menuTreeVos = ListUtil.copyEntityToVo(menuList, new MenuTreeVo());
        menuTreeVos.sort(Comparator.comparing(MenuTreeVo::getSort));
        return menuTreeVos.stream().filter(menuTreeVo -> menuTreeVo.getParentId()==null||menuTreeVo.getParentId()==0)
                .peek(menuTreeVo -> menuTreeVo.setChildren(getChildren(menuTreeVo,menuTreeVos)))
                .collect(Collectors.toList());
    }
}
